﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using Ignitron.EEngine.Model;
using OpenTK.Graphics.OpenGL;

namespace Ignitron.EEngine.Adapters.OpenGL
{
    /// <summary>
    /// Class representing an OpenTK texture
    /// </summary>
    internal class OpenTKTexture: ETexture
    {
        /// <summary>
        /// The bitmap
        /// </summary>
        private Bitmap mTexture;

        /// <summary>
        /// Texture index
        /// </summary>
        protected int mTextureIndex;

        /// <summary>
        /// Returns the bitmap object
        /// </summary>
        internal Bitmap Bitmap
        {
            get { return mTexture; }
        }


        /// <summary>
        /// Loads a texture
        /// </summary>
        public override bool Load(string filePath)
        {
            try
            {
                mTexture = new Bitmap(filePath);
            }
            catch
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// Binds the texture to the OpenGL subsystem
        /// </summary>
        internal virtual void BindTexture(bool lightingEnabled)
        {
            if (mTexture == null)
                throw new ApplicationException("Texture was not loaded.");

            var ptrTexture = mTexture.LockBits(new Rectangle(0, 0, mTexture.Width, mTexture.Height),
                ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

            // bind the texture
            GL.GenTextures(1, out mTextureIndex);
            GL.BindTexture(TextureTarget.Texture2D, mTextureIndex);


            if (lightingEnabled)
            {
                GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (float)TextureEnvMode.Modulate);
            }
            else
            {
                GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (float)TextureEnvMode.Replace);
            }

            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (float)TextureMinFilter.Linear);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (float)TextureMagFilter.Linear);
            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Three, ptrTexture.Width, ptrTexture.Height,
                0, OpenTK.Graphics.OpenGL.PixelFormat.Bgr, PixelType.UnsignedByte, ptrTexture.Scan0);
            mTexture.UnlockBits(ptrTexture);
        }

        /// <summary>
        /// Frees resources after binding the texture
        /// </summary>
        internal virtual void FreeAfterBinding()
        {
            GL.BindTexture(TextureTarget.Texture2D, 0);
            GL.DeleteTexture(mTextureIndex);
        }
    }
}
